/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.diplomka.servicelayer.gamelogic.managerimpl;

import cz.fi.muni.diplomka.common.Coordinates;
import cz.fi.muni.diplomka.common.enumeration.BuildingType;
import cz.muni.fi.diplomka.datalayer.dao.BuildingInCityDao;
import cz.muni.fi.diplomka.datalayer.dao.BuildingInProgressDao;
import cz.muni.fi.diplomka.datalayer.daoimpl.BuildingInCityDaoImpl;
import cz.muni.fi.diplomka.datalayer.daoimpl.BuildingInProgressDaoImpl;
import cz.muni.fi.diplomka.datalayer.entity.BuildingInCityEntity;
import cz.muni.fi.diplomka.datalayer.entity.BuildingInProgressEntity;
import cz.muni.fi.diplomka.servicelayer.dto.BuildingInCity;
import cz.muni.fi.diplomka.servicelayer.dto.BuildingInProgress;
import cz.muni.fi.diplomka.servicelayer.gamelogic.manager.CityBuildingManager;
import cz.muni.fi.diplomka.servicelayer.xmlconvertors.LimitsConvertor;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;

/**
 *
 * @author Jakub Kutil
 */
public class CityBuildingManagerImpl implements CityBuildingManager {

    private BuildingInCityDao buildingInCityDao = new BuildingInCityDaoImpl();
    private BuildingInProgressDao buildingInProgressDao = new BuildingInProgressDaoImpl();
    private Mapper mapper = new DozerBeanMapper();

    @Override
    public void buildBuilding(Long cityId, BuildingInCity buildingInCity, Coordinates coordinates) {
        if (cityId == null) {
            throw new IllegalArgumentException("CityId can not be null.");
        }
        if (buildingInCity == null) {
            throw new IllegalArgumentException("BuildingInCity can not be null.");
        }
        if (coordinates == null) {
            throw new IllegalArgumentException("Coordinates can not be null.");
        }
        BuildingInProgress buildingInProgress = new BuildingInProgress();
        buildingInProgress.setCityId(cityId);
        buildingInProgress.setCoordinates(coordinates);
        buildingInProgress.setTimeOfFinish(new Timestamp((long) (System.currentTimeMillis() + 1000 * 60 * buildingInCity.getLevels().get(buildingInCity.getLevel()).getPriceTime())));
        buildingInProgress.setName(BuildingType.valueOf(buildingInCity.getName().toString()));
        buildingInProgressDao.addBuildingInProgress(mapper.map(buildingInProgress, BuildingInProgressEntity.class));
    }

    @Override
    public void upgradeBuilding(Long cityId, Coordinates coordinates) {
        if (cityId == null) {
            throw new IllegalArgumentException("CityID can not be null.");
        }

        if (coordinates == null) {
            throw new IllegalArgumentException("Coordinates can not be null.");
        }

        BuildingInCity buildingInCity = mapper.map(buildingInCityDao.getBuildingInCityAtPosition(cityId, coordinates), BuildingInCity.class);
        BuildingInProgress buildingInProgress = mapper.map(buildingInProgressDao.getBuildingInProgressAtPosition(cityId, coordinates), BuildingInProgress.class);

        if (buildingInCity.getName().equals(BuildingType.Empty)) {

            buildingInCity.setCityId(cityId);
            buildingInCity.setCoordinates(coordinates);
            buildingInCity.setLevel(1);
            buildingInCity.setName(buildingInProgress.getName());
        } else {
            buildingInCity.setLevel(buildingInCity.getLevel() + 1);
        }
        buildingInProgressDao.deleteBuildingInProgress(cityId, coordinates);

        buildingInCityDao.editBuildingInCity(mapper.map(buildingInCity, BuildingInCityEntity.class));
    }

    @Override
    public void razeBuilding(Long cityId, Coordinates coordinates) {
        if (cityId == null) {
            throw new IllegalArgumentException("CityID can not be null.");
        }

        if (coordinates == null) {
            throw new IllegalArgumentException("Coordinates can not be null.");
        }
        BuildingInCityEntity buildingInCity = buildingInCityDao.getBuildingInCityAtPosition(cityId, coordinates);
        buildingInCity.setLevel(1);
        buildingInCity.setName(BuildingType.Empty);
        buildingInCityDao.editBuildingInCity(buildingInCity);
        buildingInProgressDao.deleteBuildingInProgress(cityId, coordinates);
    }

    @Override
    public List<BuildingInProgress> getBuildingsInProgress(Long cityId) {
        if (cityId == null) {
            throw new IllegalArgumentException("CityID can not be null.");
        }
        List<BuildingInProgress> buildingsInProgress = new ArrayList<>();
        for (BuildingInProgressEntity buildingInProgressEntity : buildingInProgressDao.getAllBuildingsInProgressForCity(cityId)) {
            buildingsInProgress.add(mapper.map(buildingInProgressEntity, BuildingInProgress.class));
        }
        return buildingsInProgress;
    }

    @Override
    public List<BuildingInCity> getAllBuildingsInCity(Long cityId) {
        if (cityId == null) {
            throw new IllegalArgumentException("CityID can not be null.");
        }
        List<BuildingInCity> buildingsInCity = new ArrayList<>();

        for (BuildingInCityEntity BuildingInCityEntity : buildingInCityDao.getAllBuildingInCity(cityId)) {
            buildingsInCity.add(mapper.map(BuildingInCityEntity, BuildingInCity.class));
        }

        return buildingsInCity;
    }

    @Override
    public BuildingInCity getBuildingAt(Long cityId, Coordinates coordinates) {
        if (cityId == null) {
            throw new IllegalArgumentException("CityID can not be null.");
        }

        if (coordinates == null) {
            throw new IllegalArgumentException("Coordinates can not be null.");
        }

        return mapper.map(buildingInCityDao.getBuildingInCityAtPosition(cityId, coordinates), BuildingInCity.class);
    }

    @Override
    public List<BuildingInCity> getAllBuildingsInCityOfType(Long cityId, BuildingType buildingType) {
        if (cityId == null) {
            throw new IllegalArgumentException("CityID can not be null.");
        }

        if (buildingType == null) {
            throw new IllegalArgumentException("BuildingType can not be null.");
        }
        List<BuildingInCity> buildingsInCityOfType = new ArrayList<>();

        for (BuildingInCityEntity buildingInCityEntity : buildingInCityDao.getAllBuildingInCityOfType(cityId, buildingType)) {
            buildingsInCityOfType.add(mapper.map(buildingInCityEntity, BuildingInCity.class));
        }

        return buildingsInCityOfType;
    }

    @Override
    public void createStartingBuildingsForCity(Long cityId) {
        LimitsConvertor limitsConvertor = new LimitsConvertor();

        if (cityId == null) {
            throw new IllegalArgumentException("CityId cant be null");
        }
        List<BuildingInCity> limits = limitsConvertor.getStartingBuildingsFromXML();

        for (BuildingInCity b : limits) {

            b.setCityId(cityId);
            buildingInCityDao.addBuildingInCity(mapper.map(b, BuildingInCityEntity.class));
        }
    }

    @Override
    public BuildingInProgress getBuildingInProgressAtPosition(Long cityId, Coordinates coordinates) {
        if (cityId == null) {
            throw new IllegalArgumentException("CityID can not be null.");
        }
        if (coordinates == null) {
            throw new IllegalArgumentException("Coordinates can not be null.");
        }
        return mapper.map(buildingInProgressDao.getBuildingInProgressAtPosition(cityId, coordinates), BuildingInProgress.class);

    }
    
    @Override
    public List<BuildingInProgress> getAllBuildingInProgress(){
        List<BuildingInProgress> buildingsInProgress = new ArrayList<>();

        for (BuildingInProgressEntity buildingInProgressEntity : buildingInProgressDao.getAllBuildingsInProgress()) {
            buildingsInProgress.add(mapper.map(buildingInProgressEntity, BuildingInProgress.class));
        }

        return buildingsInProgress;
        
    }
}
